package com.ruoyi.socket.handler;

import com.ruoyi.socket.DeviceClientInfoDO;
import com.ruoyi.socket.server.SocketClientStore;
import com.ruoyi.socket.server.WebsocketUtils;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelId;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;


@Component("clientHandler")
@Scope("prototype")
@Slf4j
@ChannelHandler.Sharable
public class WebSocketServerHandler extends SimpleChannelInboundHandler<Object> {

    @Autowired
    private SocketClientStore socketClientStore;

    @Autowired
    private MessageHandler messageHandler;


    @Override
    public void channelRead0(ChannelHandlerContext ctx, Object msg) {
        if (msg instanceof FullHttpRequest) {
            // 传统的HTTP接入
            log.info("FullHttpRequest");
        } else if (msg instanceof TextWebSocketFrame) {
            //文本消息接入
            DeviceClientInfoDO deviceClientInfoDO = getDeviceClientInfoDO(ctx, ((TextWebSocketFrame) msg).text());
            messageHandler.getResultMsg(deviceClientInfoDO, ctx);
        } else if (msg instanceof ByteBuf) {
            //二进制流接入
            DeviceClientInfoDO deviceClientInfoDO = getDeviceClientInfoDO(ctx, WebsocketUtils.getMsg((ByteBuf) msg));
            messageHandler.getResultMsg(deviceClientInfoDO, ctx);
        } else {
            log.info(String.valueOf(msg));
        }
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.channel().flush();
    }


    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // 这里是客户端连接成功之后，调用此处，这里可以清除一些已经不在线的客户端ctx
        log.info("Client new id:" + ctx.channel().id());
        this.socketClientStore.storeClientId(ctx);
        super.channelActive(ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        ChannelId id = ctx.channel().id();
        log.info("Client closed id:" + id);
        this.socketClientStore.delClientId(id.toString());
        super.channelInactive(ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        log.info("Client exception id:" + ctx.channel().id());
        this.socketClientStore.delClientId(ctx.channel().id().toString());
        String message = cause.getMessage();
        log.info("error = " + message);
        if (!message.contains("远程主机强迫关闭了一个现有的连接") && !message.contains("Connection reset by peer")) {
            cause.printStackTrace();
        }
        ctx.close();
    }

    private DeviceClientInfoDO getDeviceClientInfoDO(ChannelHandlerContext ctx, String msg) {
        DeviceClientInfoDO clientInfo = new DeviceClientInfoDO();
        clientInfo.setMessage(msg);
        clientInfo.setServerIp(WebsocketUtils.getServerPort(ctx)[0]);
        clientInfo.setServerPort(WebsocketUtils.getServerPort(ctx)[1]);
        clientInfo.setClientKey(ctx.channel().id().toString());
        clientInfo.setClientPort(WebsocketUtils.getClientPort(ctx)[1]);
        clientInfo.setClientIp(WebsocketUtils.getClientPort(ctx)[0]);
        return clientInfo;
    }


}
